/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>

#include <cstring>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <vector>

#include <mc/common.h>
#include <test_utilities/test_base.h>
#include <mc/crypto/crc32.h>
#include <mc/memory.h>
#include <ncsi/ncsi_huawei.h>
#include <ncsi/ncsi_protocol.h>
#include <ncsi/ncsi_socket.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <ncsi_over_mctp/ncsi_over_mctp_standard.h>
#include <smbus/smbus.h>

#include "../../../../../drivers/pcie_nic_card/hisi/interface/network_port.h"
#include "../../../../../drivers/pcie_nic_card/hisi/interface/network_port/link_info.h"
#include "../../../../../drivers/pcie_nic_card/hisi/interface/network_port/metrics.h"
#include "../../../../../drivers/pcie_nic_card/hisi/interface/network_port/data_center_bridging.h"
#include "../../../../../drivers/pcie_nic_card/hisi/interface/network_port/lldp_receive.h"
#include <map>

// 声明外部函数
namespace dev {
void set_mctp_request_handler(std::function<bool(const mc::dict&, const std::vector<uint8_t>&,
                                                  std::string&)> handler);
}

namespace {

constexpr uint16_t host_to_be16(uint16_t value) {
    return static_cast<uint16_t>(((value & 0x00FFU) << 8U) | ((value & 0xFF00U) >> 8U));
}

template <typename T>
std::string to_sized_string(const T& value, size_t length) {
    return std::string(reinterpret_cast<const char*>(&value), length);
}

// Mock smbus - 支持根据 opcode 返回不同的响应
class mock_smbus : public dev::smbus {
public:
    mock_smbus() : dev::smbus(nullptr) {
    }

    void set_send_request_result(const std::string& data_result) {
        m_data_result = data_result;
    }

    void set_send_request_result_for_opcode(uint16_t opcode, const std::string& data_result) {
        m_opcode_results[opcode] = data_result;
    }

    // 重写 send_request 方法，直接返回设置的响应数据
    std::string send_request(mc::mutable_dict request) {
        uint16_t opcode = request.contains("opcode") ? request["opcode"].as<uint16_t>() : 0x404;
        
        // 根据 opcode 获取对应的响应数据
        std::string response_data = m_data_result;
        if (m_opcode_results.find(opcode) != m_opcode_results.end()) {
            response_data = m_opcode_results[opcode];
        }
        
        return response_data;
    }

    std::pair<bool, std::vector<uint8_t>> send_and_receive(const std::string& data,
                                                           uint32_t len) override {
        // 从请求数据中解析 opcode
        // dev::smbus 请求格式：reserved(2) + opcode(2) + offset(4) + length(4)
        uint16_t request_opcode = 0x04;  // 默认值
        if (data.length() >= 4) {
            // opcode 在 reserved (2 bytes) 之后
            request_opcode = static_cast<uint8_t>(data[2]) | (static_cast<uint8_t>(data[3]) << 8);
        }

        // 根据 opcode 获取对应的响应数据
        std::string response_data = m_data_result;
        if (m_opcode_results.find(request_opcode) != m_opcode_results.end()) {
            response_data = m_opcode_results[request_opcode];
        }

        // 如果数据为空，返回空响应
        if (response_data.empty()) {
            return std::make_pair(false, std::vector<uint8_t>());
        }

        uint32_t data_len = static_cast<uint32_t>(response_data.length());

        std::vector<uint8_t> response;
        response.reserve(12 + data_len + 4);

        response.push_back(0x00);
        response.push_back(0x00);

        // opcode (2 bytes) - 从请求中获取
        response.push_back(static_cast<uint8_t>(request_opcode & 0xFF));
        response.push_back(static_cast<uint8_t>((request_opcode >> 8) & 0xFF));

        response.push_back(static_cast<uint8_t>(data_len & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 8) & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 16) & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 24) & 0xFF));

        response.push_back(static_cast<uint8_t>(data_len & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 8) & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 16) & 0xFF));
        response.push_back(static_cast<uint8_t>((data_len >> 24) & 0xFF));

        response.insert(response.end(), response_data.begin(), response_data.end());

        std::string bin_data(reinterpret_cast<const char*>(response.data()), response.size());
        uint32_t crc32 = mc::crypto::CRC32().calculate(bin_data, 0, true);
        response.push_back(static_cast<uint8_t>(crc32 & 0xFF));
        response.push_back(static_cast<uint8_t>((crc32 >> 8) & 0xFF));
        response.push_back(static_cast<uint8_t>((crc32 >> 16) & 0xFF));
        response.push_back(static_cast<uint8_t>((crc32 >> 24) & 0xFF));

        return std::make_pair(true, response);
    }

private:
    std::string m_data_result;
    std::map<uint16_t, std::string> m_opcode_results;
};

// Test service
class test_service : public mc::engine::service {
public:
    test_service(const std::string& name) : mc::engine::service(name) {
    }
};

// Test fixture
class network_port_test : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service.init();
        m_test_service.start();
        m_mctp = mc::make_shared<dev::mctp>(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, "");
    }

    static void TearDownTestSuite() {
        m_test_service.stop();
        m_mctp.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        m_port = mc::make_shared<dev::NetworkPort>();
        m_port->PortId.set_value(static_cast<uint8_t>(1));
    }

    void TearDown() override {
        // 等待所有异步操作完成（如定时器回调），避免在服务停止时回调仍在执行
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        // 清理实例成员
        m_port.reset();
        dev::set_mctp_request_handler(nullptr);
    }

    mc::shared_ptr<dev::NetworkPort> m_port;
    static test_service m_test_service;
    static mc::shared_ptr<dev::mctp> m_mctp;
};

// 静态成员初始化
test_service network_port_test::m_test_service{"bmc.kepler.test_nic"};
mc::shared_ptr<dev::mctp> network_port_test::m_mctp;

// ========== NetworkPort_Metrics 测试 ==========

// Test fixture for NetworkPort_Metrics
class network_port_metrics_test : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service.init();
        m_test_service.start();
        m_mctp = mc::make_shared<dev::mctp>(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, "");
        m_metrics = mc::make_shared<dev::NetworkPort_Metrics>();
    }

    static void TearDownTestSuite() {
        m_test_service.stop();
        m_metrics.reset();
        m_mctp.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
    }

    void TearDown() override {
        // 等待所有异步操作完成（如定时器回调），避免在服务停止时回调仍在执行
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        dev::set_mctp_request_handler(nullptr);
    }

    static test_service m_test_service;
    static mc::shared_ptr<dev::mctp> m_mctp;
    static mc::shared_ptr<dev::NetworkPort_Metrics> m_metrics;
};

// 静态成员初始化
test_service network_port_metrics_test::m_test_service{"bmc.kepler.test_metrics"};
mc::shared_ptr<dev::mctp> network_port_metrics_test::m_mctp;
mc::shared_ptr<dev::NetworkPort_Metrics> network_port_metrics_test::m_metrics;

// 辅助函数：创建get_port_metrics响应
std::string make_get_port_metrics_response() {
    controller_packet_statistics_rsp response{};
    response.rsp_code   = host_to_be16(COMMAND_COMPLETED);
    response.reason_code = host_to_be16(NOERROR_OR_NOREASON);
    response.counters_cleared_from_last_read_ms_bits = 0;
    response.counters_cleared_from_last_read_ls_bists = 0;
    response.total_bytes_received                = mc::hton(static_cast<uint64_t>(1000));
    response.total_bytes_transmitted              = mc::hton(static_cast<uint64_t>(2000));
    response.total_unicast_packets_received      = mc::hton(static_cast<uint64_t>(100));
    response.total_multicast_packets_received    = mc::hton(static_cast<uint64_t>(200));
    response.total_broadcast_packets_received     = mc::hton(static_cast<uint64_t>(300));
    response.total_unicast_packets_transmitted   = mc::hton(static_cast<uint64_t>(400));
    response.total_multicast_packets_transmitted = mc::hton(static_cast<uint64_t>(500));
    response.total_broadcast_packets_transmitted = mc::hton(static_cast<uint64_t>(600));
    response.fcs_received_errors                 = mc::hton(static_cast<uint32_t>(10));
    response.runt_packets_received               = mc::hton(static_cast<uint32_t>(20));
    response.jabber_packets_received             = mc::hton(static_cast<uint32_t>(30));
    response.single_collision_transmit_frames     = mc::hton(static_cast<uint32_t>(40));
    response.multiple_collision_transmit_frames  = mc::hton(static_cast<uint32_t>(50));
    response.late_collision_frames               = mc::hton(static_cast<uint32_t>(60));
    response.excessive_collision_frames          = mc::hton(static_cast<uint32_t>(70));
    response.alignment_errors                    = mc::hton(static_cast<uint32_t>(80));
    response.check_sum                           = 0;
    response.FCS                                 = 0;
    return std::string(reinterpret_cast<const char*>(&response),
                       GET_CONTROLLER_PACKET_STATISTICS_RSP_LEN);
}

TEST_F(network_port_metrics_test, update_port_metrics_by_ncsi_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = make_get_port_metrics_response();
        return true;
    });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_metrics->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(1000), 1);

    bool result = m_metrics->update_port_metrics_by_ncsi(1);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_metrics->RXFrames.get_value().as<uint64_t>(), 1000);
    EXPECT_EQ(m_metrics->TXFrames.get_value().as<uint64_t>(), 2000);
    EXPECT_EQ(m_metrics->RXUnicastFrames.get_value().as<uint64_t>(), 100);
    EXPECT_EQ(m_metrics->TXUnicastFrames.get_value().as<uint64_t>(), 400);
    EXPECT_EQ(m_metrics->RXMulticastFrames.get_value().as<uint64_t>(), 200);
    EXPECT_EQ(m_metrics->TXMulticastFrames.get_value().as<uint64_t>(), 500);
    EXPECT_EQ(m_metrics->RXBroadcastFrames.get_value().as<uint64_t>(), 300);
    EXPECT_EQ(m_metrics->TXBroadcastFrames.get_value().as<uint64_t>(), 600);
    EXPECT_EQ(m_metrics->RXFCSErrors.get_value().as<uint64_t>(), 10);
    EXPECT_EQ(m_metrics->RXUndersizeFrames.get_value().as<uint64_t>(), 20);
    EXPECT_EQ(m_metrics->RXOversizeFrames.get_value().as<uint64_t>(), 30);
    EXPECT_EQ(m_metrics->TXSingleCollisions.get_value().as<uint64_t>(), 40);
    EXPECT_EQ(m_metrics->TXMultipleCollisions.get_value().as<uint64_t>(), 50);
    EXPECT_EQ(m_metrics->TXLateCollisions.get_value().as<uint64_t>(), 60);
    EXPECT_EQ(m_metrics->TXExcessiveCollisions.get_value().as<uint64_t>(), 70);
    EXPECT_EQ(m_metrics->RXFrameAlignmentErrors.get_value().as<uint64_t>(), 80);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_metrics->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_metrics_test, update_port_metrics_by_ncsi_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string&) { return false; });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_metrics->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(1000), 1);

    bool result = m_metrics->update_port_metrics_by_ncsi(1);
    EXPECT_FALSE(result);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_metrics->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_metrics_test, start_ncsi_update_task_huawei_sets_ncsi_object) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = make_get_port_metrics_response();
        return true;
    });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_metrics->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(100), 1);

    bool result = m_metrics->update_port_metrics_by_ncsi(1);
    EXPECT_TRUE(result);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_metrics->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_metrics_test, stop_ncsi_update_task_cleans_up_resources) {
    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_metrics->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(100), 1);
    m_metrics->stop_ncsi_update_task();
    m_metrics->stop_ncsi_update_task();  // 再次调用应该不会崩溃
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========== NetworkPort_DataCenterBridging 测试 ==========

// Test fixture for NetworkPort_DataCenterBridging
class network_port_data_center_bridging_test : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service.init();
        m_test_service.start();
        m_mctp = mc::make_shared<dev::mctp>(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, "");
    }

    static void TearDownTestSuite() {
        m_test_service.stop();
        m_mctp.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        m_dcbx = mc::make_shared<dev::NetworkPort_DataCenterBridging>();
    }

    void TearDown() override {
        m_dcbx.reset();
        m_mctp.reset();
    }

    mc::shared_ptr<dev::NetworkPort_DataCenterBridging> m_dcbx;
    static test_service m_test_service;
    static mc::shared_ptr<dev::mctp> m_mctp;
};

// 静态成员初始化
test_service network_port_data_center_bridging_test::m_test_service{"bmc.kepler.test_dcbx"};
mc::shared_ptr<dev::mctp> network_port_data_center_bridging_test::m_mctp;

// 辅助函数：创建get_dcbx_status响应
std::string make_get_dcbx_status_response() {
    oem_huawei_dcbx_status_rsp_t response{};
    response.public_rsp_header.response_code   = host_to_be16(0);
    response.public_rsp_header.reason_code     = host_to_be16(0);
    response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
    response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_DCBX_STATUS;
    // 初始化数组
    for (int i = 0; i < MCTP_NCSI_DCBX_FIELD_LEN; i++) {
        response.cos2_up[i] = static_cast<uint8_t>(i);
        response.up_pgid[i] = static_cast<uint8_t>(i + 10);
        response.pgpct[i]   = static_cast<uint8_t>(i + 20);
        response.strict[i]  = static_cast<uint8_t>(i + 30);
    }
    response.pfcmap = 0x55;
    response.check_sum = 0;
    return std::string(reinterpret_cast<const char*>(&response),
                       OEM_HUAWEI_DCBX_STATUS_RSP_LEN);
}

TEST_F(network_port_data_center_bridging_test, update_dcbx_status_by_ncsi_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = make_get_dcbx_status_response();
        return true;
    });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_dcbx->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(1000), 1);

    bool result = m_dcbx->update_dcbx_status_by_ncsi(1);
    EXPECT_TRUE(result);

    auto up2cos = m_dcbx->Up2cos.get_value().as<std::vector<uint8_t>>();
    auto uppgid = m_dcbx->Uppgid.get_value().as<std::vector<uint8_t>>();
    auto pgpct  = m_dcbx->Pgpct.get_value().as<std::vector<uint8_t>>();
    auto strict = m_dcbx->PgStrict.get_value().as<std::vector<uint8_t>>();

    EXPECT_EQ(up2cos.size(), MCTP_NCSI_DCBX_FIELD_LEN);
    EXPECT_EQ(uppgid.size(), MCTP_NCSI_DCBX_FIELD_LEN);
    EXPECT_EQ(pgpct.size(), MCTP_NCSI_DCBX_FIELD_LEN);
    EXPECT_EQ(strict.size(), MCTP_NCSI_DCBX_FIELD_LEN);

    for (int i = 0; i < MCTP_NCSI_DCBX_FIELD_LEN; i++) {
        EXPECT_EQ(up2cos[i], static_cast<uint8_t>(i));
        EXPECT_EQ(uppgid[i], static_cast<uint8_t>(i + 10));
        EXPECT_EQ(pgpct[i], static_cast<uint8_t>(i + 20));
        EXPECT_EQ(strict[i], static_cast<uint8_t>(i + 30));
    }

    EXPECT_EQ(m_dcbx->Pfcmap.get_value().as<uint8_t>(), 0x55);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_dcbx->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_data_center_bridging_test, update_dcbx_status_by_ncsi_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string&) { return false; });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_dcbx->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(1000), 1);

    bool result = m_dcbx->update_dcbx_status_by_ncsi(1);
    EXPECT_FALSE(result);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_dcbx->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_data_center_bridging_test, start_ncsi_update_task_huawei_sets_ncsi_object) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = make_get_dcbx_status_response();
        return true;
    });

    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_dcbx->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(100), 1);

    bool result = m_dcbx->update_dcbx_status_by_ncsi(1);
    EXPECT_TRUE(result);
    
    // 显式停止定时器，避免在 TearDown 时定时器仍在运行
    m_dcbx->stop_ncsi_update_task();
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_data_center_bridging_test, stop_ncsi_update_task_cleans_up_resources) {
    auto ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_dcbx->start_ncsi_update_task_huawei(ncsi, mc::milliseconds(100), 1);
    m_dcbx->stop_ncsi_update_task();
    m_dcbx->stop_ncsi_update_task();  // 再次调用应该不会崩溃
    // 等待所有异步操作完成（如定时器回调），避免在 TearDown 时回调仍在执行
    // 增加等待时间，确保定时器回调完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========== NetworkPort_LLDPReceive 测试 ==========
// NetworkPort_LLDPReceive 类只有默认构造函数和析构函数，没有其他方法，不需要测试

// ========== NetworkPort 测试 ==========

// Mock ncsi_over_mctp_huawei 类
class mock_ncsi_over_mctp_huawei : public dev::ncsi_over_mctp_huawei {
public:
    mock_ncsi_over_mctp_huawei(dev::mctp& mctp_obj) : dev::ncsi_over_mctp_huawei(mctp_obj) {
    }

    // 设置各个方法的返回值
    void set_get_bdf_result(bool result, dev::ncsi_bdf_info_t bdf = {}) {
        m_get_bdf_result = result;
        m_bdf_info       = bdf;
    }

    void set_get_mac_addr_result(bool result, uint8_t* mac_addr = nullptr) {
        m_get_mac_addr_result = result;
        if (mac_addr) {
            std::memcpy(m_mac_addr, mac_addr, 6);
        }
    }

    void set_get_default_mac_addr_result(bool result, uint8_t* mac_addr = nullptr) {
        m_get_default_mac_addr_result = result;
        if (mac_addr) {
            std::memcpy(m_default_mac_addr, mac_addr, 6);
        }
    }

    void set_enable_lldp_capability_result(bool result) {
        m_enable_lldp_capability_result = result;
    }

    void set_disable_lldp_capability_result(bool result) {
        m_disable_lldp_capability_result = result;
    }

    void set_get_lldp_capability_result(bool result, uint8_t capability = 0) {
        m_get_lldp_capability_result = result;
        m_lldp_capability            = capability;
    }

    void set_enable_lldp_tx_result(bool result) {
        m_enable_lldp_tx_result = result;
    }

    void set_enable_lldp_tx_old_result(bool result) {
        m_enable_lldp_tx_old_result = result;
    }

    void set_disable_lldp_tx_result(bool result) {
        m_disable_lldp_tx_result = result;
    }

    void set_disable_lldp_tx_old_result(bool result) {
        m_disable_lldp_tx_old_result = result;
    }

    void set_get_lldp_tx_enable_result(bool result, uint8_t enable = 0) {
        m_get_lldp_tx_enable_result = result;
        m_lldp_tx_enable            = enable;
    }

    // 重写方法（注意：基类方法不是虚函数，所以不能使用 override）
    bool get_bdf(uint8_t package_id, uint8_t channel_id, dev::ncsi_bdf_info_t* bdf_info) {
        if (m_get_bdf_result && bdf_info) {
            *bdf_info = m_bdf_info;
        }
        return m_get_bdf_result;
    }

    bool get_mac_addr(uint8_t package_id, uint8_t channel_id, uint8_t* mac_addr,
                      uint8_t len) {
        if (m_get_mac_addr_result && mac_addr && len >= 6) {
            std::memcpy(mac_addr, m_mac_addr, 6);
        }
        return m_get_mac_addr_result;
    }

    bool get_default_mac_addr(uint8_t package_id, uint8_t channel_id, uint8_t* mac_addr,
                              uint8_t len) {
        if (m_get_default_mac_addr_result && mac_addr && len >= 6) {
            std::memcpy(mac_addr, m_default_mac_addr, 6);
        }
        return m_get_default_mac_addr_result;
    }

    bool enable_lldp_capability(uint8_t package_id, uint8_t channel_id) {
        return m_enable_lldp_capability_result;
    }

    bool disable_lldp_capability(uint8_t package_id, uint8_t channel_id) {
        return m_disable_lldp_capability_result;
    }

    bool get_lldp_capability(uint8_t package_id, uint8_t channel_id,
                             uint8_t* lldp_capability) {
        if (m_get_lldp_capability_result && lldp_capability) {
            *lldp_capability = m_lldp_capability;
        }
        return m_get_lldp_capability_result;
    }

    bool enable_lldp_tx(uint8_t package_id, uint8_t channel_id) {
        return m_enable_lldp_tx_result;
    }

    bool enable_lldp_tx_old(uint8_t package_id, uint8_t channel_id) {
        return m_enable_lldp_tx_old_result;
    }

    bool disable_lldp_tx(uint8_t package_id, uint8_t channel_id) {
        return m_disable_lldp_tx_result;
    }

    bool disable_lldp_tx_old(uint8_t package_id, uint8_t channel_id) {
        return m_disable_lldp_tx_old_result;
    }

    bool get_lldp_tx_enable(uint8_t package_id, uint8_t channel_id,
                            uint8_t* lldp_tx_enable) {
        if (m_get_lldp_tx_enable_result && lldp_tx_enable) {
            *lldp_tx_enable = m_lldp_tx_enable;
        }
        return m_get_lldp_tx_enable_result;
    }

private:
    bool                      m_get_bdf_result = false;
    dev::ncsi_bdf_info_t      m_bdf_info      = {};
    bool            m_get_mac_addr_result            = false;
    uint8_t         m_mac_addr[6]                   = {};
    bool            m_get_default_mac_addr_result    = false;
    uint8_t         m_default_mac_addr[6]           = {};
    bool            m_enable_lldp_capability_result = false;
    bool            m_disable_lldp_capability_result = false;
    bool            m_get_lldp_capability_result     = false;
    uint8_t         m_lldp_capability               = 0;
    bool            m_enable_lldp_tx_result          = false;
    bool            m_enable_lldp_tx_old_result      = false;
    bool            m_disable_lldp_tx_result         = false;
    bool            m_disable_lldp_tx_old_result     = false;
    bool            m_get_lldp_tx_enable_result      = false;
    uint8_t         m_lldp_tx_enable                = 0;
};

// 测试 mac_addr_to_hex_string 工具函数
// 注意：mac_addr_to_hex_string 在 network_port.cpp 中定义，在 dev 命名空间中
// 但由于它没有在头文件中声明，我们需要通过 NetworkPort 类来测试它
// 或者直接测试使用它的函数

// 由于 mac_addr_to_hex_string 是内部函数，我们通过测试使用它的函数来间接测试
// 这里我们测试 update_mac_addr_by_ncsi 来间接测试 mac_addr_to_hex_string
TEST_F(network_port_test, mac_addr_to_hex_string_via_update_mac_addr) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    mock_ncsi->set_get_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "12:34:56:78:9A:BC");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, mac_addr_to_hex_string_via_update_default_mac_addr) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->PermanentMACAddress.get_value().as<std::string>(), "00:00:00:00:00:00");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, mac_addr_to_hex_string_via_update_default_mac_addr_all_ff) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->PermanentMACAddress.get_value().as<std::string>(), "FF:FF:FF:FF:FF:FF");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 update_bdf_by_ncsi
TEST_F(network_port_test, update_bdf_by_ncsi_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    dev::ncsi_bdf_info_t bdf;
    bdf.bus      = 0x01;
    bdf.device  = 0x02;
    bdf.function = 0x03;
    mock_ncsi->set_get_bdf_result(true, bdf);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_bdf_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->BDF.get_value().as<std::string>(), "0000:01:02.3");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_bdf_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_bdf_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_bdf_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 update_mac_addr_by_ncsi
TEST_F(network_port_test, update_mac_addr_by_ncsi_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    mock_ncsi->set_get_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "12:34:56:78:9A:BC");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_mac_addr_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_mac_addr_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_mac_addr_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 update_default_mac_addr_by_ncsi
TEST_F(network_port_test, update_default_mac_addr_by_ncsi_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
    mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->PermanentMACAddress.get_value().as<std::string>(), "AA:BB:CC:DD:EE:FF");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_default_mac_addr_by_ncsi_updates_mac_when_zero) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
    mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->MACAddress.set_value("00:00:00:00:00:00");

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "11:22:33:44:55:66");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_default_mac_addr_by_ncsi_updates_mac_when_na) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
    mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->MACAddress.set_value("N/A");

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "11:22:33:44:55:66");

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_default_mac_addr_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_default_mac_addr_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->update_default_mac_addr_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 enable_lldp_capability_by_ncsi
TEST_F(network_port_test, enable_lldp_capability_by_ncsi_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_capability_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->enable_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, enable_lldp_capability_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_capability_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->enable_lldp_capability_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 disable_lldp_capability_by_ncsi
TEST_F(network_port_test, disable_lldp_capability_by_ncsi_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_capability_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->disable_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, disable_lldp_capability_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_capability_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->disable_lldp_capability_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 get_lldp_capability_by_ncsi
TEST_F(network_port_test, get_lldp_capability_by_ncsi_already_enabled) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->LLDPEnabled.set_value(true);

    bool result = m_port->get_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_capability_by_ncsi_capability_non_zero) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_capability_result(true, 1);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->LLDPEnabled.set_value(false);

    bool result = m_port->get_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_capability_by_ncsi_capability_zero_enable_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_capability_result(true, 0);
    mock_ncsi->set_enable_lldp_capability_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->LLDPEnabled.set_value(false);

    bool result = m_port->get_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_capability_by_ncsi_capability_zero_enable_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_capability_result(true, 0);
    mock_ncsi->set_enable_lldp_capability_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->LLDPEnabled.set_value(false);

    bool result = m_port->get_lldp_capability_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_capability_by_ncsi_get_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_capability_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->LLDPEnabled.set_value(false);

    bool result = m_port->get_lldp_capability_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 enable_lldp_tx_by_ncsi
TEST_F(network_port_test, enable_lldp_tx_by_ncsi_new_command_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_tx_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->enable_lldp_tx_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_TRUE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, enable_lldp_tx_by_ncsi_new_command_failure_old_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_tx_result(false);
    mock_ncsi->set_enable_lldp_tx_old_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->enable_lldp_tx_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_TRUE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, enable_lldp_tx_by_ncsi_both_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_tx_result(false);
    mock_ncsi->set_enable_lldp_tx_old_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->enable_lldp_tx_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 disable_lldp_tx_by_ncsi
TEST_F(network_port_test, disable_lldp_tx_by_ncsi_new_command_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_tx_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->disable_lldp_tx_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_FALSE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, disable_lldp_tx_by_ncsi_new_command_failure_old_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_tx_result(false);
    mock_ncsi->set_disable_lldp_tx_old_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->disable_lldp_tx_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_FALSE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, disable_lldp_tx_by_ncsi_both_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_tx_result(false);
    mock_ncsi->set_disable_lldp_tx_old_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->disable_lldp_tx_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 get_lldp_tx_enable_by_ncsi
TEST_F(network_port_test, get_lldp_tx_enable_by_ncsi_enabled) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_tx_enable_result(true, 1);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->get_lldp_tx_enable_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_TRUE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_tx_enable_by_ncsi_disabled) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_tx_enable_result(true, 0);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->get_lldp_tx_enable_by_ncsi();
    EXPECT_TRUE(result);
    EXPECT_FALSE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, get_lldp_tx_enable_by_ncsi_failure) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_get_lldp_tx_enable_result(false);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->get_lldp_tx_enable_by_ncsi();
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 SendNcsiTestPacket
TEST_F(network_port_test, SendNcsiTestPacket_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = "test_response";
        return true;
    });

    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->SendNcsiTestPacket(0x01, "test_data");
    EXPECT_TRUE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_test, SendNcsiTestPacket_not_initialized) {
    // 不设置 ncsi_over_mctp_huawei
    bool result = m_port->SendNcsiTestPacket(0x01, "test_data");
    EXPECT_FALSE(result);
}

TEST_F(network_port_test, SendNcsiTestPacket_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string&) { return false; });

    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->SendNcsiTestPacket(0x01, "test_data");
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_test, SendNcsiTestPacket_empty_response) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        rsp = "";
        return true;
    });

    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->SendNcsiTestPacket(0x01, "test_data");
    EXPECT_FALSE(result);

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

// 测试 SetLLDPTxEnable
TEST_F(network_port_test, SetLLDPTxEnable_enable) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_enable_lldp_tx_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->SetLLDPTxEnable(true);
    EXPECT_TRUE(result);
    EXPECT_TRUE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, SetLLDPTxEnable_disable) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    mock_ncsi->set_disable_lldp_tx_result(true);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));

    bool result = m_port->SetLLDPTxEnable(false);
    EXPECT_TRUE(result);
    EXPECT_FALSE(m_port->LLDPEnabled.get_value().as<bool>());

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 update_mac_addr_by_smbus
TEST_F(network_port_test, update_mac_addr_by_smbus_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    mc::mutable_dict request_template{{"opcode", 0x404}};
    std::string response_data;
    // port_id=1, PF_VF=0x1234, mac_addr=0x112233445566
    response_data += static_cast<char>(1);                    // port
    response_data += static_cast<char>(0x34);                 // PF_VF low
    response_data += static_cast<char>(0x12);                 // PF_VF high
    response_data += static_cast<char>(0x11);                 // mac[0]
    response_data += static_cast<char>(0x22);                 // mac[1]
    response_data += static_cast<char>(0x33);                 // mac[2]
    response_data += static_cast<char>(0x44);                 // mac[3]
    response_data += static_cast<char>(0x55);                 // mac[4]
    response_data += static_cast<char>(0x66);                 // mac[5]
    mock_smbus_obj->set_send_request_result_for_opcode(0x404, response_data);
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    m_port->update_mac_addr_by_smbus(1);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "11:22:33:44:55:66");

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_mac_addr_by_smbus_empty_response) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    mock_smbus_obj->set_send_request_result("");
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    // 应该不会崩溃，也不会更新MAC地址
    m_port->update_mac_addr_by_smbus(1);

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_mac_addr_by_smbus_port_not_match) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    // port_id=2, 不匹配
    response_data += static_cast<char>(2);
    response_data += static_cast<char>(0x34);
    response_data += static_cast<char>(0x12);
    response_data += static_cast<char>(0x11);
    response_data += static_cast<char>(0x22);
    response_data += static_cast<char>(0x33);
    response_data += static_cast<char>(0x44);
    response_data += static_cast<char>(0x55);
    response_data += static_cast<char>(0x66);
    mock_smbus_obj->set_send_request_result_for_opcode(0x404, response_data);
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    // 应该不会更新MAC地址
    m_port->update_mac_addr_by_smbus(1);

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_mac_addr_by_smbus_multiple_ports) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    // 第一个端口：port_id=0, mac_addr=0x112233445566
    response_data += static_cast<char>(0);
    response_data += static_cast<char>(0x34);
    response_data += static_cast<char>(0x12);
    response_data += static_cast<char>(0x11);
    response_data += static_cast<char>(0x22);
    response_data += static_cast<char>(0x33);
    response_data += static_cast<char>(0x44);
    response_data += static_cast<char>(0x55);
    response_data += static_cast<char>(0x66);
    // 第二个端口：port_id=1, mac_addr=0xAABBCCDDEEFF
    response_data += static_cast<char>(1);
    response_data += static_cast<char>(0x56);
    response_data += static_cast<char>(0x78);
    response_data += static_cast<char>(0xAA);
    response_data += static_cast<char>(0xBB);
    response_data += static_cast<char>(0xCC);
    response_data += static_cast<char>(0xDD);
    response_data += static_cast<char>(0xEE);
    response_data += static_cast<char>(0xFF);
    mock_smbus_obj->set_send_request_result_for_opcode(0x404, response_data);
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    m_port->update_mac_addr_by_smbus(1);
    EXPECT_EQ(m_port->MACAddress.get_value().as<std::string>(), "AA:BB:CC:DD:EE:FF");

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, update_mac_addr_by_smbus_partial_data) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    // 数据长度不足9字节，应该不会崩溃
    response_data += static_cast<char>(1);
    response_data += static_cast<char>(0x11);
    response_data += static_cast<char>(0x22);
    mock_smbus_obj->set_send_request_result_for_opcode(0x404, response_data);
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    // 应该不会崩溃，也不会更新MAC地址
    m_port->update_mac_addr_by_smbus(1);

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 start_smbus_update_task
TEST_F(network_port_test, start_smbus_update_task_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    response_data += static_cast<char>(1);
    response_data += static_cast<char>(0x34);
    response_data += static_cast<char>(0x12);
    response_data += static_cast<char>(0x11);
    response_data += static_cast<char>(0x22);
    response_data += static_cast<char>(0x33);
    response_data += static_cast<char>(0x44);
    response_data += static_cast<char>(0x55);
    response_data += static_cast<char>(0x66);
    mock_smbus_obj->set_send_request_result_for_opcode(0x404, response_data);

    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(100), 1);
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    m_port->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_test, start_smbus_update_task_nullptr) {
    m_port->start_smbus_update_task(nullptr, mc::milliseconds(1000), 1);
    // 应该不会崩溃
}

// 测试 stop_smbus_update_task
TEST_F(network_port_test, stop_smbus_update_task_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    m_port->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);
    m_port->stop_smbus_update_task();
    m_port->stop_smbus_update_task();  // 再次调用应该不会崩溃
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 start_ncsi_update_task_huawei 和定时器回调 - 10秒任务
TEST_F(network_port_test, start_ncsi_update_task_huawei_timer_10s_task) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    mock_ncsi->set_get_mac_addr_result(true, mac_addr);

    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100));
    // 等待定时器触发（10秒任务）
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 start_ncsi_update_task_huawei 和定时器回调 - 120秒任务（第1次）
TEST_F(network_port_test, start_ncsi_update_task_huawei_timer_120s_task_first) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    mock_ncsi->set_get_mac_addr_result(true, mac_addr);
    dev::ncsi_bdf_info_t bdf;
    bdf.bus      = 0x01;
    bdf.device  = 0x02;
    bdf.function = 0x03;
    mock_ncsi->set_get_bdf_result(true, bdf);
    uint8_t default_mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
    mock_ncsi->set_get_default_mac_addr_result(true, default_mac);
    mock_ncsi->set_get_lldp_capability_result(true, 1);
    mock_ncsi->set_get_lldp_tx_enable_result(true, 1);

    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100));
    // 等待定时器触发（第1次，会执行120秒任务）
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 start_ncsi_update_task_huawei 计数器重置
TEST_F(network_port_test, start_ncsi_update_task_huawei_counter_reset) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    mock_ncsi->set_get_mac_addr_result(true, mac_addr);

    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(10));
    // 等待足够的时间让计数器达到120（需要1200次，每次10ms，总共12000ms）
    // 为了测试，我们只等待一小段时间，主要测试定时器启动和基本回调
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    m_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 stop_ncsi_update_task
TEST_F(network_port_test, stop_ncsi_update_task_success) {
    auto mock_ncsi = std::make_shared<mock_ncsi_over_mctp_huawei>(*m_mctp);
    m_port->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000));
    m_port->stop_ncsi_update_task();
    m_port->stop_ncsi_update_task();  // 再次调用应该不会崩溃
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========== NetworkPort_LinkInfo 测试 ==========

// 辅助函数：创建 GET_LINK_STATUS 响应
std::string make_get_link_status_response(uint8_t link_flag = 0x01, uint8_t speed_duplex = 0x08) {
    link_status_rsp response{};
    response.rsp_code             = host_to_be16(COMMAND_COMPLETED);
    response.reason_code          = host_to_be16(NOERROR_OR_NOREASON);
    response.lnk_sts.link_flag    = link_flag;
    response.lnk_sts.speed_duplex = speed_duplex;
    return to_sized_string(response, GET_LINK_STATUS_RSP_LEN);
}

// Test fixture for NetworkPort_LinkInfo
class network_port_link_info_test : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service.init();
        m_test_service.start();
        m_mctp = mc::make_shared<dev::mctp>(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, "");
    }

    static void TearDownTestSuite() {
        m_test_service.stop();
        m_mctp.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        m_link_info = mc::make_shared<dev::NetworkPort_LinkInfo>();
    }

    void TearDown() override {
        // 等待所有异步操作完成（如定时器回调），避免在服务停止时回调仍在执行
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        // 清理实例成员
        if (m_link_info) {
            m_link_info.reset();
        }
    }

    static test_service              m_test_service;
    static mc::shared_ptr<dev::mctp> m_mctp;
    mc::shared_ptr<dev::NetworkPort_LinkInfo> m_link_info;
};

test_service                              network_port_link_info_test::m_test_service{"bmc.kepler.test_link_info"};
mc::shared_ptr<dev::mctp>                 network_port_link_info_test::m_mctp;

// 测试 convert_link_status
TEST_F(network_port_link_info_test, convert_link_status_down) {
    uint8_t result = m_link_info->convert_link_status(0x00);
    EXPECT_EQ(result, 0);  // DOWN
}

TEST_F(network_port_link_info_test, convert_link_status_up) {
    uint8_t result = m_link_info->convert_link_status(0x01);
    EXPECT_EQ(result, 1);  // UP
}

TEST_F(network_port_link_info_test, convert_link_status_invalid) {
    uint8_t result = m_link_info->convert_link_status(0xFF);
    EXPECT_EQ(result, 255);  // 无效值
}

TEST_F(network_port_link_info_test, convert_link_status_other_values) {
    // 测试其他值
    EXPECT_EQ(m_link_info->convert_link_status(0x02), 255);
    EXPECT_EQ(m_link_info->convert_link_status(0x10), 255);
    EXPECT_EQ(m_link_info->convert_link_status(0x80), 255);
}

// 测试 update_link_status_by_ncsi
TEST_F(network_port_link_info_test, update_link_status_by_ncsi_success) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
        EXPECT_TRUE(data.empty());
        // link_flag=1 (UP), speed_duplex=8 (10000Mbps, full duplex)
        rsp = make_get_link_status_response(0x01, 0x08);
        return true;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_ncsi(1);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 0x01);
    EXPECT_EQ(m_link_info->SpeedMbps.get_value().as<uint32_t>(), 10000U);
    EXPECT_TRUE(m_link_info->FullDuplex.get_value().as<bool>());

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_link_info_test, update_link_status_by_ncsi_down) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
        EXPECT_TRUE(data.empty());
        // link_flag=0 (DOWN)
        rsp = make_get_link_status_response(0x00, 0x00);
        return true;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_ncsi(1);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 0x00);
    EXPECT_EQ(m_link_info->SpeedMbps.get_value().as<uint32_t>(), 0U);
    EXPECT_FALSE(m_link_info->FullDuplex.get_value().as<bool>());

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_link_info_test, update_link_status_by_ncsi_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_ncsi(1);
    EXPECT_FALSE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 255);  // 无效值
    EXPECT_EQ(m_link_info->SpeedMbps.get_value().as<uint32_t>(), 0U);
    EXPECT_FALSE(m_link_info->FullDuplex.get_value().as<bool>());

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_link_info_test, DISABLED_update_link_status_by_ncsi_not_initialized) {
    // 不设置 ncsi_over_mctp_huawei
    bool result = m_link_info->update_link_status_by_ncsi(1);
    EXPECT_FALSE(result);
}

TEST_F(network_port_link_info_test, update_link_status_by_ncsi_invalid_response_size) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
        EXPECT_TRUE(data.empty());
        // 返回错误大小的响应
        rsp = "invalid_size";
        return true;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_ncsi(1);
    EXPECT_FALSE(result);

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

// 测试 start_ncsi_update_task_huawei 和 stop_ncsi_update_task
TEST_F(network_port_link_info_test, start_ncsi_update_task_huawei_success) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
        EXPECT_TRUE(data.empty());
        rsp = make_get_link_status_response(0x01, 0x08);
        return true;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100), 1);

    // 等待定时器触发
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    // 验证状态已更新
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 0x01);

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

TEST_F(network_port_link_info_test, stop_ncsi_update_task_success) {
    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100), 1);
    m_link_info->stop_ncsi_update_task();
    // 再次调用应该不会崩溃
    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, stop_ncsi_update_task_multiple_calls) {
    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100), 1);
    m_link_info->stop_ncsi_update_task();
    m_link_info->stop_ncsi_update_task();
    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试 update_link_status_by_smbus
TEST_F(network_port_link_info_test, update_link_status_by_smbus_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    // 创建包含多个端口状态的响应数据
    // port_id=0: 0x01 (UP)
    response_data += static_cast<char>(0x01);
    // port_id=1: 0x00 (DOWN)
    response_data += static_cast<char>(0x00);
    // port_id=2: 0x01 (UP)
    response_data += static_cast<char>(0x01);
    mock_smbus_obj->set_send_request_result_for_opcode(0x0403, response_data);
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_smbus(1);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 0);  // DOWN

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, update_link_status_by_smbus_port_0_up) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    response_data += static_cast<char>(0x01);  // port_id=0: UP
    response_data += static_cast<char>(0x00);  // port_id=1: DOWN
    mock_smbus_obj->set_send_request_result_for_opcode(0x0403, response_data);
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 0);

    bool result = m_link_info->update_link_status_by_smbus(0);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 1);  // UP

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, update_link_status_by_smbus_empty_response) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    mock_smbus_obj->set_send_request_result("");
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 1);

    bool result = m_link_info->update_link_status_by_smbus(1);
    EXPECT_FALSE(result);

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, update_link_status_by_smbus_invalid_status_value) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    response_data += static_cast<char>(0xFF);  // 无效值
    mock_smbus_obj->set_send_request_result_for_opcode(0x0403, response_data);
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(1000), 0);

    bool result = m_link_info->update_link_status_by_smbus(0);
    EXPECT_TRUE(result);
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 255);  // 无效值

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, DISABLED_update_link_status_by_smbus_not_initialized) {
    // 不设置 smbus_obj
    bool result = m_link_info->update_link_status_by_smbus(1);
    EXPECT_FALSE(result);
}

// 测试 start_smbus_update_task 和 stop_smbus_update_task
TEST_F(network_port_link_info_test, start_smbus_update_task_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    response_data += static_cast<char>(0x01);
    mock_smbus_obj->set_send_request_result_for_opcode(0x0403, response_data);
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(100), 0);

    // 等待定时器触发
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    // 验证状态已更新
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 1);

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, DISABLED_start_smbus_update_task_nullptr) {
    // 传入 nullptr 应该不会崩溃
    m_link_info->start_smbus_update_task(nullptr, mc::milliseconds(1000), 1);
    // 验证 update_link_status_by_smbus 会失败
    bool result = m_link_info->update_link_status_by_smbus(1);
    EXPECT_FALSE(result);
}

TEST_F(network_port_link_info_test, stop_smbus_update_task_success) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(100), 1);
    m_link_info->stop_smbus_update_task();
    // 再次调用应该不会崩溃
    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(network_port_link_info_test, stop_smbus_update_task_multiple_calls) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(100), 1);
    m_link_info->stop_smbus_update_task();
    m_link_info->stop_smbus_update_task();
    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 测试定时器回调 - NCSI
TEST_F(network_port_link_info_test, ncsi_timer_callback_updates_status) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
        EXPECT_TRUE(data.empty());
        // link_flag=1 (UP), speed_duplex=8 (10000Mbps, full duplex)
        rsp = make_get_link_status_response(0x01, 0x08);
        return true;
    });

    auto mock_ncsi = std::make_shared<dev::ncsi_over_mctp_huawei>(*m_mctp);
    m_link_info->start_ncsi_update_task_huawei(mock_ncsi, mc::milliseconds(100), 1);

    // 等待定时器触发多次
    std::this_thread::sleep_for(std::chrono::milliseconds(350));

    // 验证状态已更新
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 0x01);
    EXPECT_EQ(m_link_info->SpeedMbps.get_value().as<uint32_t>(), 10000U);
    EXPECT_TRUE(m_link_info->FullDuplex.get_value().as<bool>());

    m_link_info->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    dev::set_mctp_request_handler(nullptr);
}

// 测试定时器回调 - SMBus
TEST_F(network_port_link_info_test, smbus_timer_callback_updates_status) {
    auto mock_smbus_obj = mc::make_shared<mock_smbus>();
    std::string response_data;
    response_data += static_cast<char>(0x01);  // port_id=0: UP
    mock_smbus_obj->set_send_request_result_for_opcode(0x0403, response_data);
    m_link_info->start_smbus_update_task(mock_smbus_obj, mc::milliseconds(100), 0);

    // 等待定时器触发多次
    std::this_thread::sleep_for(std::chrono::milliseconds(350));

    // 验证状态已更新
    EXPECT_EQ(m_link_info->LinkStatus.get_value().as<uint8_t>(), 1);

    m_link_info->stop_smbus_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

} // namespace

